#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>

#include "p_lib.h"
#include "pub.h"
 #include "socket_base.h"
 #include "server_connect.h"


char NetCOnfig[][512] ={
    "46086:46001\n",
    "46044:46000\n",
    "45286:45201|45204\n",
    "45686:45608|45606\n",
    "50286:50219|50212|50218|50216\n",
    "51086:51010|51011|51001|51089\n",
    "52086:52003|52005|52000|52018|52099\n",
    "52586:52501|52505|52503"
};

pthread_mutex_t mutex_sock_fd = PTHREAD_MUTEX_INITIALIZER;



int GetServerIPByDN(char *hostname, char *IP)
{	
	struct hostent *host;	
	struct in_addr in;	
	struct sockaddr_in addr_in;	

	if((hostname == NULL)||(IP == NULL))
	{
		printf("Get IP prameter error!!!\n");
		return -1;
	}

	if((host = gethostbyname(hostname)) != NULL)		
	{			
		memcpy(&addr_in.sin_addr.s_addr, host->h_addr, 4);			
		in.s_addr = addr_in.sin_addr.s_addr;	
		printf("Domain name : %s \n", hostname);			
		printf("IP length is: %d \n", host->h_length);			
		printf("Type : %d \n", host->h_addrtype);			
		printf( "IP got by dns is : %s \n", IP);
		
		if(memcmp(inet_ntoa(in), IP, IP_LEN))
			memcpy(IP, inet_ntoa(in), IP_LEN);

		return 0;
	}

	printf("gethostbyname error!!!\n");
	return -2;
}

int GetAddr_Str(char *Src, Server_Port_Ip *para)
{
	int i = 0;
	int j = 0;
	char *p = NULL;
	char *buf = Src;
	char *outer_ptr = NULL;
	char *inner_ptr = NULL;

    if(Src == NULL)
        return -1;

    while((p = strtok_r(buf, ",", &outer_ptr)))
    {
        buf = p;
        p = strtok_r(buf, ":", &inner_ptr);
		if(p && inner_ptr)
		{
        	if(i < 3)
        	{
        	    memcpy(para->IP[i], p, strlen(p));
				para->Port[i] = atoi(inner_ptr);
        	    printf( "the the ip[%d] is %s, the port[%d] is %d\n", i, para->IP[i], i, para->Port[i]);
        	}
        	else if(i == 3)
        	{
				memcpy(para->domainName, inner_ptr, strlen(inner_ptr));
				for(j = 0; j < DOMAIN_NAME_LEN; j++)
				{
					if((para->domainName[j] == '\n')||(para->domainName[j] == '\r')||(para->domainName[j] == '\t'))
						para->domainName[j] = '\0';
				}
				printf( "Domain name is %s\n", para->domainName);
        	}
        	i++;
		}
        buf = NULL;
    }

    return i;
}

int IP_Check(const char *str)  
{  
    struct in_addr addr;  
    int ret;  
    volatile int local_errno;  
  
    errno = 0;  
    ret = inet_pton(AF_INET, str, &addr);  
    local_errno = errno;  
    if (ret > 0)  
        printf( "\"%s\" is a valid IPv4 address\n", str);  
    else if (ret < 0)  
        printf( "EAFNOSUPPORT: %s\n", strerror(local_errno));  
    else   
        printf( "\"%s\" is not a valid IPv4 address\n", str);  
  
    return ret;  
}  


int ConnectServer(char* sIP, int iPort)
{
	int socketfd = 0;
	
	socketfd = TCP_ConnectToServerTimeout(sIP, iPort, 5);
	if(socketfd <= 0)
	{
		switch(errno)
		{
			case ECONNREFUSED://refuse
				socketfd = CONCT_ERR_NEED_SWAP_IP;
				break;
			case ETIMEDOUT://timeout
			case EINPROGRESS: //progress is in
				socketfd = CONCT_ERR_SWAP_IP_BY_CNT;
				break;
			
			case ENETUNREACH://net work is unreachable
				socketfd = CONCT_ERR_SWAP_IP_BY_TIME;
				break;
		}
	}

	return socketfd;
}

/*
int SetNetConfig(void)
{
	int i, num;
    FILE *fp;

    fp = fopen(NET_CONFIG_FILE, "w+");
    if(fp == NULL)
        return -1;

    fseek(fp, 0, SEEK_SET);

    num = sizeof(NetCOnfig) / (512 * sizeof(char));
    for(i = 0; i < num; i++)
        fputs(NetCOnfig[i], fp);

    fclose(fp);

	return 0;
}
*/
int DstANL_IP(char *Src, Server_Port_Ip *para)
{
	int cnt = 0;

	if(Src == NULL)
		return -1;

	if(4 != GetAddr_Str(Src, para))
		return -2;

	return 0;
}

int TCP_IP_Main(int socketfd)//add by lk 20150518
{
	TD_ComProtocl_SendFrame_t SendData;
    TD_ComProtocl_RecvFrame_t RecvData;
	memset(&SendData, 0, sizeof(SendData));
	memset(&RecvData, 0, sizeof(RecvData));

    SendData.Cmd_TAG = TAG_IP;
    SendData.FrameSize = 0;

	int status = TCP_SendMessage(socketfd, (unsigned char *)(&SendData), 2 + SendData.FrameSize);
	if(status <= 0)
	{
		DBUG("IP confrim: send error\n");
		return -1;
	}
	DBUG("the TCP_SendMessage status is %d\n", status);

	status = TCP_RecvMessage(socketfd, (unsigned char *)(&RecvData), 0, MSG_WAITALL, 30);
    if(status <= 0)
    {
        DBUG("IP confrim: recv error %d\n",status);
        return -2;
    }
	DBUG("the TCP_RecvMessage status is %d\n", status);

	return 0;
}

int AplicationConnectToServer(void)
{
	int socketfd = 0;
	int connect_cnt = 0;
	Server_Port_Ip *p_SPI = &SysCtl.ServerInfo;
	char temp_Ip[16] = {'0'};
	int  temp_Port = p_SPI->Port[0];
	memcpy(temp_Ip, p_SPI->IP[0], IP_LEN);
	
	DBUG( "Connect to %s:%d\n",temp_Ip, temp_Port);
	
	while(1)
	{
		socketfd = ConnectServer(temp_Ip, temp_Port);
		if(socketfd <= 0) //connect fail
		{
			switch(socketfd)
			{
				case CONCT_ERR_SWAP_IP_BY_CNT:
					connect_cnt ++;
					if(connect_cnt < 4) 
						break;

					DBUG( "connect to %s:%d > 3 times, swap ip connect_cnt is %d\n", temp_Ip, temp_Port, connect_cnt);
				case CONCT_ERR_NEED_SWAP_IP:
					connect_cnt = 0;
					//SwapIpPort(temp_Ip, &temp_Port);
					break;

				case CONCT_ERR_SWAP_IP_BY_TIME:
					break;

				default:
					break;
			}
			
			sleep(2);
		}
		else
		{
			SysCtl.Sockfd = socketfd;
			if(memcmp(temp_Ip, p_SPI->IP[0], IP_LEN) || (p_SPI->Port[0] != temp_Port))
			{
				memcpy(p_SPI->IP[0], temp_Ip, IP_LEN);
				p_SPI->Port[0] = temp_Port;
				//SetServerInfo(p_SPI);
			}
			break;
		}
	}

	DBUG(  "Connect server %s:%d success fd=%d\n", temp_Ip, temp_Port, SysCtl.Sockfd);

	return 1;
}

int serverInfoCal(void)
{
	char temp_Ip[16] = {'0'};
	int status = 0;
	Server_Port_Ip *p_SPI = &SysCtl.ServerInfo;
	
	status = GetServerIPByDN(p_SPI->domainName, temp_Ip);
	if(status<0)
	{
		DBUG("[serverInfoCal]: get ip by Dns fail\n");
		return -1;
	}
	else
	{
		DBUG( "[serverInfoCal]: get ip by dns success  new ip is :%s  update ip in ram now!!\n", temp_Ip);
		memcpy(p_SPI->IP[0], temp_Ip, IP_LEN);
		return 1;
	}
}
